package com.baiku.sanhos.controller;


import com.alibaba.fastjson.JSON;
import com.baiku.sanhos.domain.LoginUser;
import com.baiku.sanhos.mapper.DoctorMapper;
import com.baiku.sanhos.mapper.DrugMapper;
import com.baiku.sanhos.mapper.UserPerMapper;
import com.baiku.sanhos.pojo.entity.Doctor;
import com.baiku.sanhos.pojo.vo.*;
import com.baiku.sanhos.response.ResultVO;
import com.baiku.sanhos.response.StatusCode;
import com.baiku.sanhos.utils.FileUtil;
import com.baiku.sanhos.utils.ProfilePictureStorageService;
import com.baiku.sanhos.utils.RedisCache;
import com.baiku.sanhos.utils.RedisKeys;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.xml.transform.Result;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Slf4j
@Api(tags = "医生管理")
@RestController
@RequestMapping("/pa/doctor")
public class DoctorController {

    @Autowired
    StringRedisTemplate redisTemplated;

    @Autowired
    ProfilePictureStorageService profilePictureStorageService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserPerMapper userPerMapper;
    @Autowired
    private DoctorMapper doctorMapper;
    @Autowired
    private DrugMapper drugMapper;
    @Autowired
    private RedisTemplate<String, DoctorInfoVo> redisTemplate;
    private final String key = RedisKeys.REDIS_KEYS_DOCTOR.getValue();

    /**
     * 查询全部医生数据（包括模糊查询），并且实现分页
     *
     * @param page
     * @param pageSize
     * @return
     */
    @ApiOperation("查询全部医生数据（包括模糊查询），并且实现分页")
    @GetMapping("/selectAll")
//    @PreAuthorize("hasAuthority('DDD') or hasAuthority('AAA')")
    public ResultVO selectAll(@RequestParam("page") int page,
                              @RequestParam("pageSize") int pageSize,
                              @RequestParam("no") String no,
                              @RequestParam("nickName") String nickName) {
        Map<String, Object> map = new HashMap<>();
        int total = doctorMapper.getTotalDoctors(no, nickName);//总条数
        int totalPages = (int) Math.ceil((double) total / pageSize);//计算总页数
        List<DoctorIndexVo> doctors;
        if (totalPages == 0) {
            doctors = new ArrayList<>();
        } else {
            int offset = (page - 1) * pageSize;
            doctors = doctorMapper.selectAll(pageSize, offset, no, nickName);
        }
        map.put("doctors", doctors);
        map.put("total", total);
        return ResultVO.ok(map);
    }

    /**
     * 根据科室id查询医生的数据
     *
     * @param deptId 科室id
     * @return 集合数据
     * todo 准备从redis中查询数据
     */
    @ApiOperation("根据科室id日期查询号源的数据")
    @GetMapping("/queryByDeptId/{deptId:[0-9]+}/ByDate/{bookingDate}")
    //不要加权限
    public ResultVO listDoctorByDeptIdAndDate(@PathVariable Integer deptId, @PathVariable String bookingDate) {
        List<DoctorSourceVo> list = doctorMapper.listByDeptIdAndDate(deptId, bookingDate);
        if (list.isEmpty()) {
            return ResultVO.error(StatusCode.DATA_NOT_FOUND);
        }
        return ResultVO.ok(list);
    }

    /**
     * 根据医生工号日期查询医生的号源数据
     *
     * @param doctorNo 医生工号
     * @return 集合数据
     */
    @ApiOperation("根据医生工号日期查询号源的数据")
    @GetMapping("/queryByDoctorNo/{doctorNo}/ByDate/{bookingDate}")
    //不要加权限
    public ResultVO listDoctorByDoctorNoAndDate(@PathVariable String doctorNo, @PathVariable String bookingDate) {
        List<DoctorSourceVo> list = doctorMapper.listByDoctorNoAndDate(doctorNo, bookingDate);
        if (list.isEmpty()) {
            return ResultVO.error(StatusCode.DATA_NOT_FOUND);
        }
        return ResultVO.ok(list);
    }

    @ApiOperation("根据子科室查询医生数据")
    @GetMapping("/queryByDeptId/{deptId:[0-9]+}")
    //首页页面数据 不要加权限啦
    public ResultVO queryDoctorByDeptId(@PathVariable Integer deptId) {
        List<DoctorIndexVo> list = doctorMapper.selectByDeptId(deptId);
        return ResultVO.ok(list);
    }

    @ApiOperation("根据子级科室id查询医生的数据")
    @GetMapping("queryByChildDeptId/{childDeptId:[0-9]+}")
    public ResultVO listByChildDeptId(@PathVariable Integer childDeptId) {
        List<DoctorInfoVo> newData = new ArrayList<>();
        List<DoctorInfoVo> list = packListDocInfo();
        if (list.isEmpty()) {
            return ResultVO.error(StatusCode.DATA_NOT_FOUND);
        }
        for (DoctorInfoVo s : list) {
            if (s.getDeptId().equals(childDeptId)) {
                newData.add(s);
            }
        }
        return newData.isEmpty()?ResultVO.error(StatusCode.DATA_NOT_FOUND):ResultVO.ok(newData);

    }

    /**
     * 封装类 上面的方法和下面的代码调用相同
     *
     * @return List<DoctorInfoVo>
     */
    private List<DoctorInfoVo> packListDocInfo() {
        ListOperations<String, DoctorInfoVo> operations = redisTemplate.opsForList();
        return operations.range(key, 0, -1);
    }

    @ApiOperation("根据父级科室查询子科室和医生的数据")
    @GetMapping("/queryByParentDeptId/{parentDeptId:[0-9]+}")
    //首页页面数据 不要加权限啦
    public ResultVO listByParentDeptId(@PathVariable Integer parentDeptId) {
        List<DoctorInfoVo> newData = new ArrayList<>();
        List<DoctorInfoVo> list = packListDocInfo();
        if (list.isEmpty()) {
            return ResultVO.error(StatusCode.DATA_NOT_FOUND);
        }
        for (DoctorInfoVo s : list) {
            if (s.getLevelId().equals(parentDeptId)) {
                newData.add(s);
            }
        }
        return newData.isEmpty()?ResultVO.error(StatusCode.DATA_NOT_FOUND):ResultVO.ok(newData);
    }

    @ApiOperation("根据医生工号查询科室id")
    @GetMapping("/queryDeptIdByDoctorNo/{doctorNo}")
    //不要加权限
    public ResultVO getDeptByDoctorNo(@PathVariable String doctorNo) {
        Integer deptId = doctorMapper.getDeptByDoctorNo(doctorNo);
        return ResultVO.ok(deptId);
    }

    /**
     * 根据id来修改医生的启用，禁用状态
     *
     * @param id
     * @return
     */
    @ApiOperation("根据id来修改医生的启用，禁用状态")
    @GetMapping("/changStatus/{id}")
//    @PreAuthorize("hasAuthority('AAA')")
    public ResultVO updateById(@PathVariable Integer id) {
        Doctor doctor = doctorMapper.selectById(id);
        int status = doctor.getStatus() == 1 ? 0 : 1;
        doctorMapper.updateById(id, status);
        Doctor updateDoctorAfter = doctorMapper.selectById(id);
        return ResultVO.ok(updateDoctorAfter);
    }


    /**
     * 根据id实现多删除功能
     *
     * @param ids
     * @return
     */
    @ApiOperation("根据id实现多删除功能")
    @PostMapping("/deleteByIds")
//    @PreAuthorize("hasAuthority('AAA')")
    public ResultVO deleteByIds(@RequestBody List<Integer> ids) {
        doctorMapper.deleteByIds(ids);
        return ResultVO.ok();
    }

    /**
     * 根据id删除医生信息
     *
     * @param id
     * @return
     */
    @ApiOperation("根据id删除医生信息")
    @DeleteMapping("/deleteById/{id}")
//    @PreAuthorize("hasAuthority('AAA')")
    public ResultVO deleteById(@PathVariable Integer id) {
        DoctorIndexVo doctorIndexVo = doctorMapper.selectByIdDoctor(id);
        int num = doctorMapper.deleteById(id);
        if (num > 0) {
            userPerMapper.deleteByIdPer(doctorIndexVo.getUsername());
            return ResultVO.ok();
        }
        return ResultVO.ok();
    }

    /**
     * 模态框，新增方法
     *
     * @param doctorIndexVo
     * @return
     */
    @ApiOperation("模态框，新增方法")
    @PostMapping("/addDoctor")
//    @PreAuthorize("hasAuthority('DDD') or hasAuthority('AAA')")
    public ResultVO addDoctor(@RequestBody DoctorIndexVo doctorIndexVo) {
        int count = doctorMapper.CountNoDoctor(doctorIndexVo.getNo());
        if (count > 0) {
            return new ResultVO(StatusCode.NO_ALREADY_EXISTS);
        }
        doctorIndexVo.setPassword(passwordEncoder.encode(doctorIndexVo.getPassword()));
        doctorIndexVo.setUpdateTime(new Date());
        doctorIndexVo.setStatus(0);
        doctorIndexVo.setFlag(1);
        int num = doctorMapper.insert(doctorIndexVo);
        if (num > 0) {
            userPerMapper.insertUserPer(doctorIndexVo);
        }
        return ResultVO.ok();
    }

    /**
     * 模态框更新操作
     *
     * @param doctorIndexVo
     * @return
     */
    @ApiOperation("模态框更新操作")
    @PutMapping("/updateById")
//    @PreAuthorize("hasAuthority('DDD') or hasAuthority('AAA')")
    public ResultVO updateById(@RequestBody DoctorIndexVo doctorIndexVo) {
        boolean startsWithNumber = isStartsWithNumber(doctorIndexVo.getDeptname());
        if (startsWithNumber == true) {
            doctorMapper.updateDoctorById1(doctorIndexVo);
            return ResultVO.ok();
        }
        doctorMapper.updateDoctorById(doctorIndexVo);
        return ResultVO.ok();
    }

    public static boolean isStartsWithNumber(String deptname) {
        // 正则表达式，^表示开头，\\d表示数字，.*表示任意字符
        String regex = "^\\d.*";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(deptname);
        return matcher.matches();
    }

    /**
     * 医生信息查询模块 TODO 接口测试完成，前端未写
     * 可用于科室信息模块信息的查询
     */
    @GetMapping("/selectByName")
//    @PreAuthorize("hasAuthority('DDD')")
    public ResultVO selectByNoName(
            @RequestParam("page") int page,
            @RequestParam("pageSize") int pageSize,
            @RequestParam("no") String no,
            @RequestParam("username") String username) {
        //这里只查询status=1的数据  TODO 没有认清status 暂时理解为上班

        if (no.equals("") && username.equals("")) {
            Map<String, Object> map = new HashMap<>();
            int total = doctorMapper.getTotalDoctors(no, username);//总条数
            int totalPages = (int) Math.ceil((double) total / pageSize);//计算总页数
            List<DoctorDetailVO> doctors;
            if (totalPages == 0) {
                doctors = new ArrayList<>();
            } else {
                int offset = (page - 1) * pageSize;
                doctors = doctorMapper.selectAllNoName(pageSize, offset, no, username);
            }
            map.put("doctors", doctors);
            map.put("total", total);
            return ResultVO.ok(map);
        }
        List<DoctorDetailVO> doctorDetails = doctorMapper.selectByNoAndUserName(no, username);
        if (doctorDetails.size() == 0) {
            return new ResultVO(1007, "数据不存在");
        }
        for (DoctorDetailVO index : doctorDetails) {

            DeptVo deptVo = doctorMapper.selectByIdNoName(index.getDeptId());
            index.setDeptname(deptVo.getDeptname());
        }
        return ResultVO.ok(doctorDetails);
    }


    /**
     * 药品信息模块（增删改查操作）
     */
    @GetMapping("/SelectDrugNoName")
//    @PreAuthorize("hasAuthority('DDD')")
    public ResultVO SelectDrugNoName(@RequestParam("drugNo") String drugNo,
                                     @RequestParam("drugName") String drugName,
                                     @RequestParam("page") int page,
                                     @RequestParam("pageSize") int pageSize) {
        if (drugNo.equals("") && drugName.equals("")) {
            Map<String, Object> map = new HashMap<>();
            int total = drugMapper.SelectTotalDrugs(drugNo, drugName);//总条数
            int totalPages = (int) Math.ceil((double) total / pageSize);//计算总页数
            List<DrugVo> drugs;
            if (totalPages == 0) {
                drugs = new ArrayList<>();
            } else {
                int offset = (page - 1) * pageSize;
                drugs = drugMapper.selectAllDrugNoName(pageSize, offset, drugNo, drugName);
            }
            map.put("drugs", drugs);
            map.put("total", total);
            return ResultVO.ok(map);

        }
        List<DrugVo> drugVos = drugMapper.selectByDrugNoAndUserName(drugNo, drugName);
        if (drugVos.size() == 0) {
            return new ResultVO(1007, "数据不存在");
        }
        return ResultVO.ok(drugVos);
    }

    /**
     * 预约模版
     */
    @GetMapping("/selectByBookingUsername")
//    @PreAuthorize("hasAuthority('DDD')")
    public ResultVO selectByBookingUsername(
            @RequestParam("page") int page,
            @RequestParam("pageSize") int pageSize,
            @RequestParam("username") String username,
            @RequestParam("nickName") String nickName) {
        //这里只查询status=1的数据  TODO 没有认清status 暂时理解为上班

        if (username.equals("") && nickName.equals("")) {
            Map<String, Object> map = new HashMap<>();
            int total = doctorMapper.getTotalDoctorsBooking(username, nickName);//总条数
            int totalPages = (int) Math.ceil((double) total / pageSize);//计算总页数
            List<BookingVO> bookingVOS;
            if (totalPages == 0) {
                bookingVOS = new ArrayList<>();

            } else {
                int offset = (page - 1) * pageSize;
                bookingVOS = doctorMapper.selectAllBooking(pageSize, offset, username, nickName);
            }
            map.put("bookingVOS", bookingVOS);
            map.put("total", total);
            return ResultVO.ok(map);

        }
        List<BookingVO> bookingVOS = doctorMapper.selectByDoctorNoAndNickName(username, nickName);
        if (bookingVOS.size() == 0) {
            return new ResultVO(1007, "数据不存在");
        }
        return ResultVO.ok(bookingVOS);
    }
    /**
     * 医生的资料修改
     */
    @PostMapping("/updateEdit")

//    @PreAuthorize("hasAuthority('DDD')")

    public ResultVO updateAccountInfo(
            @RequestParam(required = false) String newPassword,
            @RequestParam(required = false) String newPhone,
            @RequestParam(required = false) String newEmail,
            @RequestParam(required = false) String currentUserAvatar


    ) {



        // 获取当前已认证的用户详细信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        System.out.println(username);

        //判断图像信息是否已经更改
        if(!currentUserAvatar.equals(doctorMapper.selectByUserName(username).getAvatar())){
            //不同删除原来的图像资源
            FileUtil.deleteFile(currentUserAvatar);

        }

        try {
            // 如果提供了新密码和新电话，进行更新
            if (newPassword != null&&!newPassword.isEmpty()) {
                BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
                String password1=passwordEncoder.encode(newPassword);

                userPerMapper.updatePassword(username, password1);
                doctorMapper.updatePassword(username, password1);
            }

            if (newPhone!= null&&!newPhone.isEmpty()) {
                userPerMapper.updatePhone(username, newPhone);
                doctorMapper.updatePhone(username, newPhone);
            }
            if (newEmail != null&&!newEmail.isEmpty()) {

                doctorMapper.updateEmail(username, newEmail);
            }
            // TODO 刷新头像地址，其他的不需要展示和关联的不修改返回
            Map<String,String> map = new HashMap<>();
            DoctorVo doctorVo = doctorMapper.selectByUserName(username);

            map.put("Avatar",doctorVo.getAvatar());

            // 返回成功响应
            return new ResultVO(2001,"更改成功",map);
        } catch (Exception e) {
            // 如果出现错误，返回错误响应
            return new ResultVO(2002,"更改失败");
        }
    }
    @PostMapping("/api/uploads")
//    @PreAuthorize("hasAuthority('DDD')")
    public String uploadImage(@RequestParam("file") MultipartFile profilePicture) {
        // 获取当前已认证的用户详细信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        System.out.println(username);

        // 如果提供了新的头像数据，进行更新保存
        if (profilePicture != null && !profilePicture.isEmpty()) {


            String newUrl= null;
            try {
                newUrl = FileUtil.uploadFile(profilePicture);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            doctorMapper.updateUrl(newUrl,username);

        }
        return "Image uploaded successfully";
    }



}
